package edu.whu.rose.clock.ssql.graphindex;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashSet;

import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;

import edu.whu.rose.clock.setup.IndexEnvironment;
import edu.whu.rose.clock.ssql.graph.SubGraphDB;

public class GraphIndexManager {

	private GraphIndexDB gidb;    //database
	
	public GraphIndexManager(Environment dbEnv, int numOfSG) {
		gidb = new GraphIndexDB(dbEnv);
	}
	
	public GraphIndexManager(Environment dbEnv, String dbName, int numOfSG) {
		gidb = new GraphIndexDB(dbEnv, dbName);
	}
	
	public static void main(String[] args) {
		File file = new File("dbEnv_graphindex");
		if (file.isDirectory()) {
			File[] files = file.listFiles();
			for (int i = 0; i < files.length; i++) {
				files[i].delete();
			}
		}
		
		IndexEnvironment ie = new IndexEnvironment("dbEnv_graphindex");
		if (!ie.openEnv()) {
			System.exit(1);
		}
		GraphIndexManager gi = new GraphIndexManager(ie.getEnvironment(), 2334);
		gi.init();

		Date startTime = new Date();
		gi.createGraphIndex("graph/vertex.txt", "dbEnv_subgraph", "stop word list.txt", 350000000l);
//		gi.search("language");
		Date endTime = new Date();
		System.out.println("Completed indexing. Time consumed: " + (endTime.getTime() - startTime.getTime()) + "ms");

		
		gi.close();
		ie.closeEnv();
	}
	
	public void init() {
		if (!gidb.openDB()) {
			System.exit(1);
		}
	}
	
	public void close() {
		gidb.closeDB();
	}
	
	public void createGraphIndex(String vertexFile, String sgdbEnv, String swlFile, long cacheSize) {
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(vertexFile));
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
		
		SubGraphDB sgdb = new SubGraphDB(sgdbEnv);
		if (!sgdb.initEnv()) {
			return;
		}
		if (!sgdb.openDB()) {
			return;
		}
		
		HashSet<String> stopwordlist = new HashSet<String>();
		try {
			BufferedReader br2 = new BufferedReader(new FileReader(swlFile));
			while (br2.ready()) {
				stopwordlist.add(br2.readLine().trim());
			}
			br2.close();
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
		
		this.createGraphIndex(br, sgdb, stopwordlist, cacheSize);
		
		try {
			br.close();
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
		
		sgdb.closeDB();
	}
	
	public void createGraphIndex(BufferedReader br, SubGraphDB sgdb, HashSet<String> stopwordlist, long cacheSize) {
		GraphIndexCache gic = new GraphIndexCache(gidb, cacheSize);
		
		int counter = 0;
		Date sDate = new Date();
		Date eDate = null;
		try {
			while (br.ready()) {
				String line = br.readLine().trim();
				if (line.length() > 0) {
					int pos = line.indexOf(" ");
					if (pos == -1) {
						System.out.println("Found wrong line: " + line);
						continue;
					}
					String key = line.substring(0, pos);
					String value = line.substring(pos).trim();
					
					//get corresponding subgraphs from vertex id (key)
					int vertex = new Integer(key).intValue();
					int[] subgraphs = null;
//					int[] sgkns = null;
					try {
						subgraphs = sgdb.getFromInvertedList(vertex);
//						sgkns = new int[subgraphs.length];
//						for (int i = 0; i < subgraphs.length; i++) {
//							sgkns[i] = sgdb.getSGKN(subgraphs[i]);
//						}
					}
					catch (DatabaseException ex) {
						ex.printStackTrace();
					}
					
					this.insertGraph(vertex, subgraphs/*, sgkns*/, value, stopwordlist, gic);
					counter++;
					if (counter % 1000 == 0) {
						System.out.println(key);
						eDate = new Date();
						System.out.println("Time exhausted: " + (eDate.getTime() - sDate.getTime()) + " ms");
						sDate = eDate;
						gic.statistic();
					}
				}
			}
			gic.flush();
			gic.statistic();
//			sgdb.addAllSGKN(sgkn);
		}
		catch (UnsupportedEncodingException ex) {
			ex.printStackTrace();
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
		catch (DatabaseException ex) {
			ex.printStackTrace();
		}
	}
	
	//parse vertex content and then send to cache for processing
	public void insertGraph(int vertex, int[] subgraphs/*, int[] sgkns*/, String value, HashSet<String> stopwordlist, GraphIndexCache gic) {
		String[] pairs = value.split("@@");
		for (int i = 0; i < pairs.length; i++) {
			String pair = pairs[i].trim();
			if (pair.length() > 0) {
				int pos = pair.indexOf(":");
				if (pos == -1) {
					System.out.println("Found wrong attr-value pair: " + pair);
					continue;
				}
				String attrName = pair.substring(0, pos).trim();
				String attrValue = pair.substring(pos + 1).trim();
				String[] keywords = null;
				if (attrName.equals("title")) {
					keywords = GraphIndexManager.parse(attrValue);
				}
				else if (attrName.equals("name")) {
					keywords = GraphIndexManager.naiveParse(attrValue);
				}
				else {
					continue;
				}
//				else {
//					keywords = GraphIndexManager.naiveParse(attrValue);
//				}
				for (int j = 0; j < keywords.length; j++) {
					String keyword = keywords[j].trim();
					String lcKeyword = keyword.toLowerCase();
					if (lcKeyword.length() > 0) {
						if (stopwordlist.contains(lcKeyword)) {
							continue;
						}
//						String keyword_attr = keyword + "@@" + attrName;
						try {
							
							gic.insert(lcKeyword, subgraphs/*, sgkns*/, vertex);
//							gic.insert(keyword_attr, subgraphs, sgkns, vertex);
						}
						catch (DatabaseException ex) {
							ex.printStackTrace();
						}
						catch (UnsupportedEncodingException ex) {
							ex.printStackTrace();
						}
					}
				}
			}
		}
	}
	
	public static String[] parse(String value) {
		String[] words = value.split(" "); 
		for (int i = 0; i < words.length; i++) {
			String word = words[i].trim();
			while (word.startsWith("(") || word.startsWith("\"") || word.startsWith("'")) {
				word = word.substring(1);
			}
			while (word.endsWith(",") || word.endsWith(".") || word.endsWith(")") || 
					word.endsWith("?") || word.endsWith(":") || word.endsWith("!") ||
					word.endsWith("\"") || word.endsWith("'")) {
				word = word.substring(0, word.length() - 1);
			}
			words[i] = word;
		}
		return words;
	}
	
	public static String[] naiveParse(String value) {
		return value.split(" ");
	}
	
//	public void search(String keyword) {
//		SubGraphDB sgdb = new SubGraphDB("dbEnv_subgraph");
//		if (!sgdb.initEnv()) {
//			return;
//		}
//		if (!sgdb.openDB()) {
//			return;
//		}
//		
//		GraphIndexItem gii = gidb.search(keyword);
//		int size = gii.getSize();
//		GraphQueryAnswer gqa = new GraphQueryAnswer(size);
//		double score2 = Math.log((double)2334 / (double)size);
//		for (int i = 0; i < size; i++) {
//			double tf = gii.getTf(i);
//			double score1 = tf;
//			double score = score1 * score2;
//			gqa.add(score, gii.getGraph(i), gii.getVertexGroup(i));
//		}
//		
//		for (int i = size - 1; i >= 0; i--) {
//			System.out.print(gqa.getScore(i) + ":   ");
//			System.out.print(gqa.getGraph(i) + " (");
//			for (int j = 0; j < gqa.getVertexGroupSize(i); j++) {
//				System.out.print(gqa.getVertex(i, j) + " ");
//			}
//			System.out.println("), ");
//		}
//	}

}
